
import * as cc from "cc";
import { AssetLoader } from "./AssetLoader";
import { loaderMgr } from "./LoaderMgr";



type Bundle = cc.AssetManager.Bundle;
export class ResourcesMgr{

    public removeBundle(nameOrUrl : string ){
        return AssetLoader.removeBundle(nameOrUrl);
    }

    public loadBundle(bundleName: string | Bundle,onComplete: LoadBundleCompleteFunc){
        AssetLoader.loadBundle(bundleName,onComplete);
    }

    public preload (key: any,paths: string|string[], type: CCAssetType,_bundle?:  Bundle | string): void
    public preload (key: any,paths: string|string[], type: CCAssetType, _onComplete?: CCCompleteCallbackWithData<RequestItem[]>,_bundle?:  Bundle | string): void
    public preload (key: any,paths: string|string[], type: CCAssetType, _onProgress: CCProgressCallback, _onComplete: CCCompleteCallbackWithData<RequestItem[]>,_bundle?:  Bundle | string): void;
    public preload (
        key: any,
        paths: string|string[],
        type: CCAssetType,
        _onProgress?: CCProgressCallback | CCCompleteCallbackWithData<RequestItem[]> | null | Bundle | string,
        _onComplete?: CCCompleteCallbackWithData<RequestItem[]> | null |  Bundle | string,
        _bundle?:  Bundle | string
    ) {
        let loader = loaderMgr.get(key);

        let obj = loader.parsingLoadArgs(_onProgress,_onComplete,_bundle);

        let {onProgress,onComplete,bundle} = obj;
        loader.loadBundleAssets(bundle,(err,bundleAsset)=>{
            if(err){
                onComplete?.(err,null);
                return;
            }
            _onProgress = (finish: number,total: number,item: cc.AssetManager.RequestItem)=>{
                onProgress?.(finish,total,item);
            }
            // 保留，否则会在父类里面解析错误
            _onComplete = (error: Error, assets: any)=>{
                onComplete?.(error,assets);
            }
            if(!Array.isArray(paths)){
                paths = [paths];
            }
            
            // 对路径进行格式化
            for (let i = 0; i < paths.length; i++) {
                paths[i] = loader.formatPath(paths[i],type);
            }
            bundleAsset.getBundle().preload(paths,type,_onProgress,_onComplete);
        });
    }


    public preloadDir (key: any,dir: string, type: CCAssetType | null,_bundle?: Bundle | string)
    public preloadDir (key: any,dir: string, type: CCAssetType | null, _onProgress: CCProgressCallback | null, _onComplete: CCCompleteCallbackWithData<RequestItem[]> | null,_bundle?: Bundle | string) 
    public preloadDir (key: any,dir: string, type: CCAssetType | null, _onComplete?: CCCompleteCallbackWithData<RequestItem[]> | null,_bundle?: Bundle | string)
    public preloadDir (
        key: any,
        dir: string,
        type?: CCAssetType,
        _onProgress?: CCProgressCallback | CCCompleteCallbackWithData<RequestItem[]>| null | Bundle | string,
        _onComplete?: CCCompleteCallbackWithData<RequestItem[]>| null | Bundle | string,
        _bundle?: Bundle | string
    ) {
        let loader = loaderMgr.get(key);
        let {onProgress,onComplete,bundle} = loader.parsingLoadArgs(_onProgress,_onComplete,_bundle);
        loader.loadBundleAssets(bundle,(err,bundleAsset )=>{
            if(err){
                onComplete?.(err,null);
                return;
            }

            _onProgress = (finish: number,total: number,item: cc.AssetManager.RequestItem)=>{
                onProgress?.(finish,total,item);
            }
            // 保留，否则会在父类里面解析错误
            _onComplete = (error: Error, assets: any)=>{
                onComplete?.(error,assets);
            }
            
            bundleAsset.getBundle().preloadDir(dir,type,_onProgress,_onComplete);
        });

    }


    public preloadScene(key: any,sceneName: string, bundle?:  cc.AssetManager.Bundle | string)
    public preloadScene(key: any,sceneName: string, onComplete?: CCCompleteCallbackNoData, bundle?:  cc.AssetManager.Bundle | string)
    public preloadScene(key: any,sceneName: string, options?:CCIAssetOptions | null, bundle?:  cc.AssetManager.Bundle | string)
    public preloadScene(key: any,sceneName: string, options?:CCIAssetOptions | null, onComplete?: CCCompleteCallbackNoData, bundle?:  cc.AssetManager.Bundle | string)
    public preloadScene(key: any,sceneName: string, onProgress?:  CCProgressCallback, onComplete?: CCCompleteCallbackNoData, bundle?:  cc.AssetManager.Bundle | string)
    public preloadScene(key: any,sceneName: string, _options?:CCIAssetOptions | null | CCProgressCallback | cc.AssetManager.Bundle | string, _onProgress?: CCProgressCallback | CCCompleteCallbackNoData | cc.AssetManager.Bundle | string, _onComplete?: CCCompleteCallbackNoData | cc.AssetManager.Bundle | string, _bundle?:  cc.AssetManager.Bundle | string){
   
     
        let loader = loaderMgr.get(key);
        let { options, onProgress, onComplete, bundle } = loader.parseParameters(_options,_onProgress,_onComplete,_bundle);
        if(!bundle){
            bundle = cc.assetManager.bundles.find((bundle)=> {
                return !!bundle.getSceneInfo(sceneName);
            });
        }
        loader.loadBundleAssets(bundle,(err,bundleAsset)=>{
            if(err){
                onComplete?.(err);
                return;
            }
            // 加载 场景资源
            bundleAsset.getBundle().preloadScene(sceneName,options,(finish: number,total: number,item: cc.AssetManager.RequestItem)=>{
                onProgress?.(finish,total,item);
            },(error: Error)=>{
                onComplete?.(error);
            });
        });
    }
    

    public loadArray<T extends cc.Asset>(key: any,paths: string[], type: CCAssetType<T>,_bundle?:  Bundle | string)
    public loadArray<T extends cc.Asset>(key: any,paths: string[], type: CCAssetType<T>,_onComplete?: CCCompleteCallbackWithData<T[]>,_bundle?:  Bundle | string)
    public loadArray<T extends cc.Asset>(key: any,paths: string[], type: CCAssetType<T>,_onProgress?: CCProgressCallback,_onComplete?: CCCompleteCallbackWithData<T[]> ,_bundle?:  Bundle | string)
    public loadArray<T extends cc.Asset>(key: any,paths: string[], type: CCAssetType<T>,_onProgress?: CCProgressCallback | CCCompleteCallbackWithData<T[]> | Bundle | string,_onComplete?: CCCompleteCallbackWithData<T[]> | Bundle | string,_bundle?:  Bundle | string){
        
        let loader = loaderMgr.get(key);

        let {onProgress,onComplete,bundle} = loader.parsingLoadArgs(_onProgress,_onComplete,_bundle);
        _onProgress = (finish: number,total: number,item: cc.AssetManager.RequestItem)=>{
            onProgress?.(finish,total,item);
        }
        // 保留，否则会在加载器类里面解析错误
        _onComplete = async (error: Error, assets: any)=>{
            onComplete?.(error,assets);
        }

        loader.loadArray(paths,type,_onProgress,_onComplete,bundle);
    }


    public load<T extends cc.Asset>(key: any,path: string, type: CCAssetType<T>,_bundle?:  cc.AssetManager.Bundle | string)
    public load<T extends cc.Asset>(key: any,path: string, type: CCAssetType<T>,_onComplete?: CCCompleteCallbackWithData,_bundle?:  cc.AssetManager.Bundle | string)
    public load<T extends cc.Asset>(key: any,path: string, type: CCAssetType<T>,_onProgress?: CCProgressCallback,_onComplete?: CCCompleteCallbackWithData ,_bundle?:  cc.AssetManager.Bundle | string)
    public load<T extends cc.Asset>(key: any,path: string, type: CCAssetType<T>,_onProgress?: CCProgressCallback | CCCompleteCallbackWithData | cc.AssetManager.Bundle | string,_onComplete?: CCCompleteCallbackWithData | cc.AssetManager.Bundle | string,_bundle?:  cc.AssetManager.Bundle | string){
        let loader = loaderMgr.get(key);

        let {onProgress,onComplete,bundle} = loader.parsingLoadArgs(_onProgress,_onComplete,_bundle);
        _onProgress = (finish: number,total: number,item: cc.AssetManager.RequestItem)=>{
            onProgress?.(finish,total,item);
        }
        // 保留，否则会在加载器类里面解析错误
        _onComplete = async (error: Error, assets: any)=>{
            onComplete?.(error,assets);
        }
        loader.load(path,type,_onProgress,_onComplete,bundle);
    }

    
    public loadDir<T extends cc.Asset>(key: any,dir: string, type: CCAssetType<T>,_bundle?: cc.AssetManager.Bundle | string)
    public loadDir<T extends cc.Asset>(key: any,dir: string, type: CCAssetType<T>,_onComplete?: CCCompleteCallbackWithData,_bundle?: cc.AssetManager.Bundle | string)  
    public loadDir<T extends cc.Asset>(key: any,dir: string, type: CCAssetType<T>,_onProgress?: CCProgressCallback,_onComplete?: CCCompleteCallbackWithData ,_bundle?:  cc.AssetManager.Bundle | string)
    public loadDir<T extends cc.Asset>(key: any,dir: string, type: CCAssetType<T>,_onProgress?: CCProgressCallback | CCCompleteCallbackWithData | cc.AssetManager.Bundle | string,_onComplete?: CCCompleteCallbackWithData | cc.AssetManager.Bundle | string,_bundle?:  cc.AssetManager.Bundle | string){
        let loader = loaderMgr.get(key);

        let {onProgress,onComplete,bundle} = loader.parsingLoadArgs(_onProgress,_onComplete,_bundle);
        _onProgress = (finish: number,total: number,item: cc.AssetManager.RequestItem)=>{
            
            onProgress?.(finish,total,item);
        }
        // 保留，否则会在加载器类里面解析错误
        _onComplete = async (error: Error, assets: any)=>{
            // await this.onComplete(error,assets);
            onComplete?.(error,assets);
        }

        loader.loadDir(dir,type,_onProgress,_onComplete,bundle);
    }
    
    public loadScene(key: any,sceneName: string,_bundle?:  cc.AssetManager.Bundle | string)
    public loadScene(key: any,sceneName: string,_onComplete?: CCCompleteCallbackWithData ,_bundle?:  cc.AssetManager.Bundle | string)
    public loadScene(key: any,sceneName: string,_onProgress: CCProgressCallback,_onComplete?: CCCompleteCallbackWithData,_bundle?:  cc.AssetManager.Bundle | string)
    public loadScene(key: any,sceneName: string,_onProgress: CCProgressCallback | CCCompleteCallbackWithData | cc.AssetManager.Bundle | string,_onComplete?: CCCompleteCallbackWithData | cc.AssetManager.Bundle | string,_bundle?:  cc.AssetManager.Bundle | string){
        let loader = loaderMgr.get(key);

        let {onProgress,onComplete,bundle} = loader.parsingLoadArgs(_onProgress,_onComplete,_bundle);
        _onProgress = (finish: number,total: number,item: cc.AssetManager.RequestItem)=>{
            onProgress?.(finish,total,item);
        }
        // 保留，否则会在加载器类里面解析错误
        _onComplete = async (error: Error, assets: any)=>{                                                                                                                                                               
            // await this.onComplete(error,assets);
            onComplete?.(error,assets);
        }
        loader.loadScene(sceneName,_onProgress,_onComplete,bundle);
    }



    // 释放单个资源
    public releaseAsset<T extends cc.Asset>(key: any,path: string, type: CCAssetType<T>){
        let loader = loaderMgr.get(key);
        loader.releaseAsset(path,type);
    }

    // 直接释放引用资源，不对包装层做判断
    public releaseAll(key: any){
        loaderMgr.releaseLoader(key);
    }



    private static _instance:ResourcesMgr = null;
    public static getInstance(): ResourcesMgr{
        if(!this._instance){
            this._instance = new ResourcesMgr();
        }
        return this._instance;
    }
}

export let resourcesMgr = ResourcesMgr.getInstance();
